﻿using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Telerik.Windows.Documents.Fixed.Model.Data;
using Telerik.Windows.Documents.Fixed.Model.Editing;

namespace Com.Lancetinc.Evs.Reports.RadPdf;

internal abstract class UIElementRendererBase
{
    internal static IDisposable SaveClip(FixedContentEditor drawingSurface, UIElement element)
    {
        Geometry clip = null;
        if (element is FrameworkElement frameworkElement)
        {
            clip = LayoutInformation.GetLayoutClip(frameworkElement);
        }

        if (clip == null)
        {
            clip = element.Clip;
        }

        var rectangleClip = clip as RectangleGeometry;
        if (rectangleClip == null)
        {
            return null;
        }

        return SaveClip(drawingSurface, rectangleClip.Rect);
    }

    internal static IDisposable SaveClip(FixedContentEditor drawingSurface, Rect rectangle)
    {
        var geometry = MathHelper.TransformRectangle(drawingSurface.Position.Matrix, rectangle);
        var pdfGeometry = PdfGeometryHelper.ConvertPathGeometry(geometry);

        return drawingSurface.PushClipping(pdfGeometry);
    }

    internal static IDisposable SaveMatrixPosition(FixedContentEditor drawingSurface, FrameworkElement element,
        bool isRoot)
    {
        if (element == null)
        {
            return null;
        }

        var transform = MathHelper.GetGeneralTransform(element, isRoot);
        var matrix = MathHelper.CreateMatrix(transform);
        if (matrix.IsIdentity)
        {
            return null;
        }

        matrix = MathHelper.Multiply(matrix, drawingSurface.Position.Matrix);
        var savePosition = drawingSurface.SavePosition();
        drawingSurface.Position = new MatrixPosition(matrix);

        return savePosition;
    }

    internal static IDisposable SaveOpacity(PdfRenderContext context, double newOpacity)
    {
        if (context.opacity != newOpacity)
        {
            var disposableOpacity = new DisposableOpacity(context);
            context.opacity = newOpacity;
            return disposableOpacity;
        }

        return null;
    }

    internal static void SetFill(PdfRenderContext context, Brush brush, double width, double height)
    {
        var fill = PdfColorHelper.ConvertBrush(brush, context.opacity, context.drawingSurface.Position, width, height);

        context.drawingSurface.GraphicProperties.IsFilled = fill != null;
        context.drawingSurface.GraphicProperties.FillColor = fill;
    }

    internal static void SetStroke(PdfRenderContext context, double thickness, Brush brush, double width, double height,
        DoubleCollection dashArray)
    {
        var stroke =
            PdfColorHelper.ConvertBrush(brush, context.opacity, context.drawingSurface.Position, width, height);
        context.drawingSurface.GraphicProperties.IsStroked = thickness != 0 && stroke != null;

        if (context.drawingSurface.GraphicProperties.IsStroked)
        {
            context.drawingSurface.GraphicProperties.StrokeThickness = thickness;
            context.drawingSurface.GraphicProperties.StrokeColor = stroke;

            if (dashArray != null)
            {
                context.drawingSurface.GraphicProperties.StrokeDashArray = dashArray;
            }
        }
    }

    internal abstract bool Render(UIElement element, PdfRenderContext context);
}